package com.qf.md.unit.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.net.HttpHeaders;
import com.qf.common.PageVO;
import com.qf.entity.md.unit.MdUnitMeasure;
import com.qf.exception.CustomerException;
import com.qf.md.unit.dao.MdUnitMeasureDao;
import com.qf.md.unit.param.DownLoadParam;
import com.qf.md.unit.param.UnitSearchParam;
import com.qf.md.unit.service.MdUnitMeasureService;
import com.qf.md.unit.vo.MeasureIdAndPrimaryIdVO;
import com.qf.sys.dao.SysUserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.function.Supplier;

/**
 * @author zdl
 * @date 2025/2/27
 */
@Service
public class MdUnitMeasureServiceImpl implements MdUnitMeasureService {
    @Resource
    private MdUnitMeasureDao mdUnitMeasureDao;


    @Override
    public PageVO<MdUnitMeasure> queryUnitPage(UnitSearchParam unitSearchParam) {
        PageHelper.startPage(unitSearchParam.getPageNum(), unitSearchParam.getPageSize());
        List<MdUnitMeasure> mdUnitMeasures = mdUnitMeasureDao.selectMeasurePage(unitSearchParam);
        PageInfo<MdUnitMeasure> mdUnitMeasurePageInfo = new PageInfo<>(mdUnitMeasures);
        if (mdUnitMeasurePageInfo != null) {
            return new PageVO<>(mdUnitMeasurePageInfo.getTotal(), mdUnitMeasurePageInfo.getList());
        }
        return null;
    }

    @Override
    public Long delUnitByMeasureId(Long measureId) {
        //查询单位ID下 是否有其他单位引用为主单位
        List<MeasureIdAndPrimaryIdVO> measureIdAndPrimaryIdVOS = mdUnitMeasureDao.selectMeasureIdAndPrimaryId(measureId);
        if (!(measureIdAndPrimaryIdVOS.isEmpty())) {
            throw new CustomerException("6009", "当前主单位下有其他单位引用，无法删除");
        }
        for (MeasureIdAndPrimaryIdVO measureIdAndPrimaryIdVO : measureIdAndPrimaryIdVOS) {
            //判断主单位是否为启用状态 启用状态 禁止删除
            if (!(measureIdAndPrimaryIdVO.getM1Flag().equals("Y"))) {
                throw new CustomerException("6008", "当前状态为启用状态，无法删除");
            }
            if (!(measureIdAndPrimaryIdVO.getM2Flag().equals("Y"))) {
                throw new CustomerException("6008", "当前状态为启用状态，无法删除");
            }
        }
        MdUnitMeasure mdUnitMeasure = mdUnitMeasureDao.selectByMeasureId(measureId);
        if (!(mdUnitMeasure.getEnableFlag().equals("Y"))) {
            throw new CustomerException("6008", "当前状态为启用状态，无法删除");
        }
        if (measureIdAndPrimaryIdVOS.isEmpty()) {
            Long i = mdUnitMeasureDao.delMeasureByMeasureId(measureId);
            if (i != 1) {
                throw new CustomerException("6001", "数据不存在");
            }
            return i;
        } else {
            throw new CustomerException("6007", "该单位下有其他单位引用");
        }
    }

    @Override
    public Long delBatchMeasureByIds(List<Long> ids) {
        if (ids.isEmpty()) {
            throw new CustomerException("6002", "传递数据无效");
        }
        for (Long id : ids) {
            MdUnitMeasure mdUnitMeasure = mdUnitMeasureDao.selectByPrimaryKey(id);
            if (mdUnitMeasure.getEnableFlag().equals("Y")){
                throw new CustomerException("6008", "当前状态为启用状态，无法删除");
            }
            if (mdUnitMeasure == null) {
                throw new CustomerException("6003", "用户不存在");
            }
        }
        return mdUnitMeasureDao.delBatchMeasureByIds(ids);
    }

    @Override
    public Long addMeasure(MdUnitMeasure mdUnitMeasure) {
        if (mdUnitMeasure == null) {
            throw new CustomerException("6002", "传递数据无效");
        }
        MdUnitMeasure mdUnitMeasure1 = mdUnitMeasureDao.selectByMeasureName(mdUnitMeasure.getMeasureCode(), mdUnitMeasure.getMeasureName());
        if (mdUnitMeasure1 != null) {
            throw new CustomerException("6004", "物料单位或名称已存在");
        }

        mdUnitMeasure.setCreateTime(new Date());
        if (mdUnitMeasureDao.addMeasure(mdUnitMeasure) != 1) {
            throw new CustomerException("6005", "新增失败");
        }
        return 1L;
    }

    @Override
    public List<MdUnitMeasure> queryAllPrimaryFlag() {
        return mdUnitMeasureDao.selectByPrimaryFlag();
    }

    @Override
    public MdUnitMeasure findByPrimaryKey(Long measureId) {
        return mdUnitMeasureDao.selectByPrimaryKey(measureId);
    }

    @Override
    public Long updateMeasure(MdUnitMeasure mdUnitMeasure) {
        mdUnitMeasure.setUpdateTime(new Date());
        if (mdUnitMeasureDao.updateMeasure(mdUnitMeasure) != 1) {
            throw new CustomerException("6006", "修改失败");
        }
        return 1L;
    }

    Long totalCount = 0L;
    @Override
    public Long uploadExcel(MultipartFile file) {
        /**
         * 每隔5条存储数据库，实际使用中可以100条，然后清理list ，方便内存回收
         */
        final int BATCH_COUNT = 100;
        /**
         * 缓存的数据
         */
        List<MdUnitMeasure> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        try {
            InputStream fileName = file.getInputStream();
            EasyExcel.read(fileName, MdUnitMeasure.class, new ReadListener<MdUnitMeasure>() {
                @Override
                public void invoke(MdUnitMeasure mdUnitMeasure, AnalysisContext analysisContext) {
                    cachedDataList.add(mdUnitMeasure);
                    // 每当缓存达到批次大小时，执行批量插入
                    if (cachedDataList.size() >= BATCH_COUNT) {
                        // 执行批量插入并累加插入的条数
                        totalCount +=   mdUnitMeasureDao.uploadBatchExcel(cachedDataList);
                        // 清空缓存数据，准备下一个批次
                        cachedDataList.clear();
                    }
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                    // 处理剩余未达到批次的数据
                    if (!cachedDataList.isEmpty()) {
                        totalCount += mdUnitMeasureDao.uploadBatchExcel(cachedDataList);
                    }
                }
            }).sheet().doRead();
        } catch (IOException e) {
            throw new CustomerException("8001", "导入失败");
        }
        Long i = totalCount;
        totalCount = 0L;
        return i;
    }

    @Override
    public void downExcel(HttpServletResponse response) {
        List<DownLoadParam> mdUnitMeasures = mdUnitMeasureDao.downloadExcel();
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系

        String fileName = "导出计量单位数据" + timeStamp;
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        } catch (UnsupportedEncodingException e) {
            throw new CustomerException("8002","导出失败");
        }
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        try {
            EasyExcel.write(response.getOutputStream(), DownLoadParam.class).sheet("模板").doWrite(mdUnitMeasures);
        } catch (IOException e) {
            throw new CustomerException("8002","导出失败");
        }
    }
    @Value("${template.path}")
    private String templatePath;
    @Override
    public void myExcelDownload(HttpServletResponse response) {
        // 设置文件名
        String filename = "计量单位模板.xlsx";
        try {
            String encodedFilename = URLEncoder.encode(filename, "UTF-8");
            // 设置响应头，让浏览器下载文件
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFilename);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        // 使用 EasyExcel 写入空数据，只写入表头
        try {
            EasyExcel.write(response.getOutputStream())
                    .withTemplate(templatePath)
                    .sheet()
                    .doWrite(() -> new ArrayList<>());
        } catch (IOException e) {
            throw new CustomerException("8003","下载失败");
        }
    }
}
